package com.baitiaojun.moments.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baitiaojun.api.domain.moments.UserDailyMoments;
import com.baitiaojun.api.domain.moments.UserMoments;
import com.baitiaojun.api.domain.user.UserInfo;
import com.baitiaojun.api.exception.ConditionException;
import com.baitiaojun.api.util.AESUtil;
import com.baitiaojun.api.util.ConstantUtil;
import com.baitiaojun.api.util.SnowFlakeUtil;
import com.baitiaojun.moments.feign.UserFeign;
import com.baitiaojun.moments.handler.RabbitMqHandler;
import com.baitiaojun.moments.mapper.UserDailyMomentsMapper;
import com.baitiaojun.moments.service.DailyMomentsService;
import com.baitiaojun.moments.service.DuplicateService;
import com.baitiaojun.moments.service.MomentsService;
import com.baitiaojun.moments.support.RedisSupport;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.*;

/**
 * @类名 UserDailyMomentsServiceImpl
 * @描述 TODO
 * @作者 白条君
 * @创建日期 2023/1/16 14:47
 * @版本 1.0
 */
@Service
public class DailyMomentsServiceImpl implements DailyMomentsService {

    @Resource
    private UserDailyMomentsMapper dailyMomentsMapper;

    @Autowired
    private RabbitMqHandler rabbitMqhandler;

    @Autowired
    private DuplicateService duplicateService;

    @Autowired
    private MomentsService momentsService;

    @Autowired
    private UserFeign userFeign;

    @Resource
    private RedisSupport redisSupport;

    @Transactional(propagation = Propagation.NESTED)
    @Override
    public void publishDailyMoments(UserDailyMoments userDailyMoments, Long userId) throws Exception {
        Long dailyMomentsId = SnowFlakeUtil.getNextId();
        userDailyMoments.setId(dailyMomentsId);
        userDailyMoments.setCreatetime(new Date());
        List<String> pictureList = userDailyMoments.getPictureList();
        //url加密
        if (pictureList.size() > 0) {
            List<JSONObject> pictureMapList = new ArrayList<>();
            AESUtil aesUtil = AESUtil.lazyGetAesUtil();
            Map<String, String> pictureMap;
            for (String picture : pictureList) {
                pictureMap = new HashMap<>();
                pictureMap.put(ConstantUtil.PICTURE_URL, aesUtil.decrypt(picture));
                JSONObject jsonObject = JSONObject.parseObject(JSONObject.toJSONString(pictureMap));
                pictureMapList.add(jsonObject);
            }
            userDailyMoments.setPictures(pictureMapList.toString());
        }
        //采用延时双删策略，先对缓存进行删除
        redisSupport.asyncDelete(userId);
        redisSupport.delete("self" + userId);
        redisSupport.delete("self" + userId + ":page");
        //存储到mysql
        this.addUserDailyMoments(userDailyMoments);
        //构建一个usermoments
        UserMoments userMoments = new UserMoments();
        userMoments.setId(SnowFlakeUtil.getNextId());
        userMoments.setUserid(userId);
        userMoments.setType(ConstantUtil.DAILY_TYPE);
        userMoments.setContentid(dailyMomentsId);
        userMoments.setCreatetime(new Date());
        //存储到mysql
        momentsService.addUserMoments(userMoments);
        //冗余存储到mysql
        Long duplicateId = duplicateService.insertDuplicate(userMoments);
        //发布到mq和redis
        rabbitMqhandler.publishMoments(userMoments, duplicateId);
    }

    @Override
    public void addUserDailyMoments(UserDailyMoments userDailyMoments) throws ConditionException {
        int res = dailyMomentsMapper.insertSelective(userDailyMoments);
        if (res == 0) {
            throw new ConditionException("添加日常动态失败");
        }
    }

    @Override
    public UserDailyMoments getDailyMoments(Long contentId, Long userId) throws Exception {
        AESUtil aesUtil = AESUtil.lazyGetAesUtil();
        UserDailyMoments userDailyMoments = dailyMomentsMapper.selectByPrimaryKey(contentId);
        userDailyMoments.setType(ConstantUtil.DAILY_TYPE);
        userDailyMoments.setCreatetime(new Date());
        String pictures = userDailyMoments.getPictures();
        if (StringUtils.isNotEmpty(pictures)) {
            List<JSONObject> jsonObjects = this.stringToJsonArray(pictures, aesUtil);
            userDailyMoments.setPictures(jsonObjects.toString());
        }
        //添加动态发布者
        UserInfo userInfo = userFeign.getUserInfo(userId);
        if (ObjectUtils.isEmpty(userInfo)) {
            throw new ConditionException("获取用户信息失败");
        }
        userInfo.setAvatar(aesUtil.encrypt(userInfo.getAvatar()));
        userInfo.setUserid(null);
        userInfo.setFollowing(null);
        userInfo.setFollowed(null);
        userInfo.setBirth(null);
        userInfo.setCoinCount(null);
        userInfo.setFansCount(null);
        userInfo.setGender(null);
        userInfo.setCreatetime(null);
        userInfo.setUpdatetime(null);
        userDailyMoments.setUserInfo(userInfo);
        return userDailyMoments;
    }

    @Override
    public void deleteDailyMoments(Long id) throws ConditionException {
        int res = dailyMomentsMapper.deleteByPrimaryKey(id);
        if (res == 0) {
            throw new ConditionException("删除日常动态失败");
        }
    }

    private List<JSONObject> stringToJsonArray(String pictures, AESUtil aesUtil) throws Exception {
        JSONArray pictureList = JSONObject.parseArray(pictures);
        List<JSONObject> jsonObjects = new ArrayList<>();
        Map<String, Object> objectMap;
        for (Object picture : pictureList) {
            JSONObject jsonObject = JSONObject.parseObject(JSONObject.toJSONString(picture));
            Object picUrl = jsonObject.get(ConstantUtil.PICTURE_URL);
            if (ObjectUtils.isNotEmpty(picUrl)) {
                objectMap = new HashMap<>();
                objectMap.put(ConstantUtil.PICTURE_URL, aesUtil.encrypt((String) picUrl));
                JSONObject jsonObject1 = JSONObject.parseObject(JSONObject.toJSONString(objectMap));
                jsonObjects.add(jsonObject1);
            }
        }
        return jsonObjects;
    }
}
